package hotel.compare.oversea.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.dto.meituan.MtHotelDetailDto;
import hotel.base.oversea.dto.switchs.SwitchMasterHotelInfoDto;
import hotel.base.oversea.service.impl.BaseServiceImpl;
import hotel.base.oversea.utils.*;
import hotel.base.oversea.utils.DateUtil;
import hotel.compare.oversea.config.service.RedisService;
import hotel.compare.oversea.entity.master.CompareCreateSubHotelLog;
import hotel.compare.oversea.entity.master.CompareHotel;
import hotel.compare.oversea.entity.master.CompareHotelUp;
import hotel.compare.oversea.entity.meituan.MtHotelDetail;
import hotel.compare.oversea.entity.switchs.SwitchHotelOnlineSetEntity;
import hotel.compare.oversea.entity.switchs.SwitchMasterHotelInfo;
import hotel.compare.oversea.entity.switchs.dto.SwitchMasterHotelInfoBaseDto;
import hotel.compare.oversea.mapper.master.CompareCreateSubHotelLogMapper;
import hotel.compare.oversea.mapper.master.CompareHotelMapper;
import hotel.compare.oversea.mapper.master.CompareHotelUpMapper;
import hotel.compare.oversea.mapper.meituan.MtHotelDetailMapper;
import hotel.compare.oversea.mapper.switchs.SwitchCreateSubHotelMapper;
import hotel.compare.oversea.mapper.switchs.SwitchHotelOnlineSetMapper;
import hotel.compare.oversea.mapper.switchs.SwitchHotelUpMapper;
import hotel.compare.oversea.mapper.switchs.SwitchMasterHotelInfoMapper;
import hotel.compare.oversea.service.CompareHotelService;
import hotel.compare.oversea.vo.CompareHotelListVO;
import hotel.compare.oversea.vo.CompareHotelVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

import static hotel.base.oversea.utils.CompareUtil.algorithm;
import static hotel.base.oversea.utils.CompareUtil.getStrPre;


/**
 * 校验后酒店
 *
 * @author Zhang·JZ
 * @date 2020-05-28
 */
@Slf4j
@Service
public class CompareHotelServiceImpl extends BaseServiceImpl<CompareHotel> implements CompareHotelService {
    @Autowired
    private SwitchHotelOnlineSetMapper switchHotelOnlineSetMapper;
    @Autowired
    private CompareHotelMapper compareHotelMapper;

    @Autowired
    private CompareCreateSubHotelLogMapper compareCreateSubHotelLogMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SwitchMasterHotelInfoMapper switchMasterHotelInfoMapper;

    @Autowired
    private MtHotelDetailMapper mtHotelDetailMapper;

    @Autowired
    private CompareHotelUpMapper compareHotelUpMapper;

    @Autowired
    SwitchCreateSubHotelMapper switchCreateSubHotelMapper;

    @Autowired
    SwitchHotelUpMapper switchHotelUpMapper;


    private Map<String, MtHotelDetailDto> meituanRedisMap = new HashMap<String, MtHotelDetailDto>();

    //需要批量新增数据库
    private List<CompareHotel> compareHotelList = new ArrayList<CompareHotel>();
    //批量转移没有校验成功的美团主键id
    private List<String> mtNoCompareIdList = new ArrayList<>();
    //批量转移名成没有校验成功的美团主键id
    private List<String> mtNoMatchNameMtIdList = new ArrayList<>();
    //批量转移校验成功的美团主键id
    private List<String> mtCompareIdList = new ArrayList<>();
    //批量转移校验成功的携程母酒店id
    private List<Integer> switchCompareIdList = new ArrayList<>();


    //通过校验的数据添加入缓存map,提供给房型校验使用
    private Map<String, String> isCompareMap = new HashMap<>();

    //线程数
    private Integer THREAD_NUM = 1;
    //线程执行类型 1：默认；2：定制
    private String THREAD_TYPE = "DEFAULT";


    /**
     * 携程美团批量执行数据库新增，删除数量
     */
    private Integer COMPARE_NUM = 20;


    /**
     * 两平台间酒店坐标定位可接受范围差
     * 单位 米
     * 20（2020-07-21 16：39 之前数据）
     */
    private Integer DISTANCE_MAX = 100;


    //上一条数据的距离
    private double lastMtSw = 0.0;

    //判断是否重复携程酒店
    private Map<String,CompareHotel> doubleSwtichMap = new HashMap();

    //当前执行总匹配成功并新增条数
    private int countTotal=0;

    /**
     * 校验酒店信息
     *
     * @return
     */
    @Override
//    @Transactional
    public Result<Boolean> compareHotel() {

        //直接从数据库 获取所有美团酒店数据
        List<MtHotelDetail> mtHotelDetailList = new ArrayList<>();

        //获取已校验后的携程-美团酒店id，防止重复校验
        List<CompareHotel> compareHotelList = compareHotelMapper.selectAll();
        if (!compareHotelList.isEmpty() && compareHotelList.size() > 0) {
            compareHotelList.forEach(compareHotel -> {
                String switch_meituan_id = compareHotel.getSwitchId() + compareHotel.getMtHotelId();
                isCompareMap.put(switch_meituan_id, "1");
            });
        }
        log.info("isCompareMap.size():{}", isCompareMap.size());

        mtHotelDetailList = mtHotelDetailMapper.selectAll();
        log.info("mtHotelDetailList.size():{}", mtHotelDetailList.size());
        mtHotelDetailList.forEach(mtHotelDetail -> {
            meituanRedisMap.put(mtHotelDetail.getMtHotelId(), (MtHotelDetailDto) Dto2Entity.populate(mtHotelDetail, new MtHotelDetailDto()));
        });


        log.info("meituanRedisMap.size():{}", meituanRedisMap.size());

        hotelMapFetch(meituanRedisMap);

        return new Result<>(true);
    }


    /**
     * 将校验过的key 从 美团缓存中移除
     *
     * @param key
     */
    public void removeMtRedisMap(String key) {
        log.info("移除 key:{}", key);
        meituanRedisMap.remove(key);
        if (redisService.exists(CommonConstants.MEITUAN_HOTEL_INFO)) {
            redisService.set(CommonConstants.MEITUAN_HOTEL_INFO, meituanRedisMap);
        }
    }

    /**
     * @Description: 携程-美团酒店校验
     * @Author: Zhang·jz
     * @date: 2020/6/28
     */
    public Result<Boolean> compareHotelBySql(Map<String, MtHotelDetailDto> meituanMap, String taskNum) {
        log.info("------------->当前执行线程：{}", taskNum);
        boolean ret = false;
        String removeKey = "";
        //遍历美团需要校验的酒店信息
        meituanHotel:
        for (Map.Entry<String, MtHotelDetailDto> meituanEntry : meituanMap.entrySet()) {
            removeKey = meituanEntry.getKey();

            MtHotelDetailDto mtHotelDetailDto = meituanEntry.getValue();
            String mtLat = mtHotelDetailDto.getMtHotelLatitude();
            String mtLng = mtHotelDetailDto.getMtHotelLongitude();
            if (ObjectUtils.isEmpty(mtLat) || ObjectUtils.isEmpty(mtLng)) {
                continue;
            }

            //左移动6位
            mtLat = String.valueOf(CompareUtil.getDouble(Double.valueOf(mtHotelDetailDto.getMtHotelLatitude())));
            mtLng = String.valueOf(CompareUtil.getDouble(Double.valueOf(mtHotelDetailDto.getMtHotelLongitude())));
            String cityName = mtHotelDetailDto.getMtHotelCityName().replaceAll("市", "");

            //如果为空则跳出
            if (ObjectUtils.isEmpty(cityName)) {
                continue;
            }

            //获取携程酒店信息
            SwitchMasterHotelInfoBaseDto switchMasterHotelInfoBaseDto = switchMasterHotelInfoMapper.selectMasterHotelByMeituan(mtLat, mtLng, cityName, DISTANCE_MAX);

            //判断是否存在数据；如果不为空，则判断成功！
            if (!ObjectUtils.isEmpty(switchMasterHotelInfoBaseDto)) {
                log.info("当前执行线程：" + taskNum + ";--" + "酒店数据校验成功；compareHotelList,执行批量新增操作;-->,compareHotelList.size{}", compareHotelList.size());

                if (!compareHotelList.isEmpty() && compareHotelList.size() >= COMPARE_NUM) {
                    //先做集合转移，以免重复进入
                    List<CompareHotel> compareHotelListNew = new ArrayList<>();
                    compareHotelListNew.addAll(compareHotelList);
                    if (compareHotelListNew.size() > 0) {
                        compareHotelList = new ArrayList<>();
                        //列表去重
                        compareHotelListNew.stream().distinct();
                    }
                    log.info("当前执行线程：" + taskNum + ";--" + "酒店数据校验成功；compareHotelListNew,执行批量新增操作;-->,compareHotelListNew.size{}", compareHotelListNew.size());

                    //新增数据库
                    int intList = compareHotelMapper.insertList(compareHotelListNew);
//                    log.info("当前执行线程："+taskNum+";--"+"酒店数据校验成功；并新增至校验表成功返回：intList-->",intList);

//                    log.info("当前执行线程："+taskNum+";--"+"将美团中校验的数据转移至 mt_hotel_detail_compare 表---开始执行");
                    //后删除
                    mtHotelDetailMapper.deleteBatchMtHotelInfoByMtIds(mtCompareIdList);
//                    log.info("当前执行线程："+taskNum+";--"+"将美团中校验的数据转移至 mt_hotel_detail_compare 表--->成功！");

                    //新增成功
                    if (intList != -1) {

                        //加入緩存
//                        if(!MapUtil.isEmpty(isCompareMap)){
//                            redisService.set(CommonConstants.COMPARE_HOTEL_ID,isCompareMap);
//                        }
//                        log.info("当前执行线程："+taskNum+";--"+"将携程酒店信息的数据转移至 switch_master_hotel_info_compare 表---开始执行");

                        switchCompareIdList = new ArrayList<>();
                        mtCompareIdList = new ArrayList<>();
                    }


                    log.info("当前执行线程：" + taskNum + ";--" + "批量执行新增操作成功！并添加入缓存！----->>>>>");

                }

                log.info("当前执行线程：" + taskNum + ";--" + " mtNoMatchNameMtIdList--->{}", mtNoMatchNameMtIdList.size());
                //校验不通过 酒店名称不匹配，将美团数据转移至 mt_hotel_detail_no_match_name 表中
                if (!mtNoMatchNameMtIdList.isEmpty() && mtNoMatchNameMtIdList.size() >= COMPARE_NUM) {
                    log.info("当前执行线程：" + taskNum + ";--" + "将美团中名称没有校验正确的数据转移至 mt_hotel_detail_no_match_name 表---开始执行");
                    //美团酒店信息、
                    int delInt = mtHotelDetailMapper.deleteBatchMtHotelInfoByMtIds(mtNoMatchNameMtIdList);
                    if (delInt != -1) {
                        mtNoMatchNameMtIdList = new ArrayList<>();
                        log.info("当前执行线程：" + taskNum + ";--" + "将美团中名称没有校验正确的数据转移至 mt_hotel_detail_no_match_name 表---执行成功！");
                    }

                }


                log.info("当前执行线程：" + taskNum + ";--" + "数据语句查询不为空,开始执行酒店校验-->");
                // 待测试
                ret = compareHotelByDto(mtHotelDetailDto, switchMasterHotelInfoBaseDto);
            } else {
                log.info("当前执行线程：" + taskNum + ";--" + "将美团中没有校验的数据转移至 mtNoCompareIdList--->{}", mtNoCompareIdList.size());
                mtNoCompareIdList.add(mtHotelDetailDto.getId());
                //每COMPARE_NUM条执行一次数据转移
                if (!mtNoCompareIdList.isEmpty() && mtNoCompareIdList.size() >= COMPARE_NUM) {
                    //将美团中没有校验的数据转移至 mt_hotel_detail_no_compare 表
                    //先转移
//                    int intBat = mtHotelDetailMapper.insertBatchNoCompareByMtIds(mtNoCompareIdList);
                    int intBat = mtHotelDetailMapper.deleteBatchMtHotelInfoByMtIds(mtNoCompareIdList);
                    //后新增
                    if (intBat != -1) {
                        mtNoCompareIdList = new ArrayList<>();
//                        log.info("当前执行线程："+taskNum+";--"+"将美团中没有校验的数据转移至 mt_hotel_detail_no_compare 表--->成功！");
                    }

                }

            }

        }

        log.info("当前执行线程：" + taskNum + ";--" + "———————————————————当前记录校验完成—————————————————>>>>>>>>");

        return new Result<>(ret);
    }


    /**
     * 重复校验单个酒店信息
     * 并新增至数据库
     *
     * @param meituanDto
     * @param switchDto
     * @return
     */
    public boolean compareHotelByDto(MtHotelDetailDto meituanDto, SwitchMasterHotelInfoBaseDto switchDto) {
        boolean ret = false;
        log.info("进入新增数据库方法MtHotelDetailDto--->{}", meituanDto);
        log.info("SwitchMasterHotelInfoBaseDto--->{}", switchDto);

        //默认未校验
        int isCompare = 0;

        //携程酒店id与美团酒店id对应关系

        //判断是否为空，不为空直接赋值
//        if(redisService.exists(CommonConstants.COMPARE_HOTEL_ID)){
//            isCompareMap = (Map<String,CompareHotel>) redisService.get(CommonConstants.COMPARE_HOTEL_ID);
//        }


        //遍历携程需要校验的酒店信息
//        switchLabel:for (Map.Entry<String, SwitchMasterHotelInfoDto> switchEntry : switchMap.entrySet()) {
        if (!ObjectUtils.isEmpty(switchDto)) {

            SwitchMasterHotelInfoBaseDto switchMasterHotelInfoDto = switchDto;

            //携程+美团id,作为唯一key
            String switch_meituan_id = "";

            CompareHotel compareHotel = new CompareHotel();
//            compareHotel.setId(StringUtil.getUUID());
            compareHotel.setState(0);//系统状态   0:正常   1:异常
            compareHotel.setRemark("");
            compareHotel.setIsCreateSub(0);//是否创建子酒店
            compareHotel.setCreateTime(new Date());
            compareHotel.setModifyTime(new Date());


            double switch_lng = 0.000000;
            double switch_lat = 0.000000;

            //优先判断google,高德坐标，百度
            if (!ObjectUtils.isEmpty(switchMasterHotelInfoDto.getGgLat()) && !ObjectUtils.isEmpty(switchMasterHotelInfoDto.getGgLng())) {
                switch_lng = switchMasterHotelInfoDto.getGgLng().doubleValue();
                switch_lat = switchMasterHotelInfoDto.getGgLat().doubleValue();
            }

            compareHotel.setSwitchLat(new BigDecimal(switch_lat).setScale(6, BigDecimal.ROUND_DOWN));
            compareHotel.setSwitchLng(new BigDecimal(switch_lng).setScale(6, BigDecimal.ROUND_DOWN));

            //酒店名称
            String switch_hotel_name = switchMasterHotelInfoDto.getHotelName();
            //地区城市名称
            String area_name = switchMasterHotelInfoDto.getCityName();

            compareHotel.setSwitchHotelId(switchMasterHotelInfoDto.getMasterHotelId());
            compareHotel.setSwitchHotelName(switch_hotel_name);

            //携程酒店所在城市
            String switchHotelCityName = switchMasterHotelInfoDto.getCityName();
            //遍历美团需要校验的酒店信息，美团经纬度需要将小数点向左移动6位
            if (!ObjectUtils.isEmpty(meituanDto)) {
                MtHotelDetailDto mtHotelDetailDto = meituanDto;

                //携程+美团id,作为唯一key
                switch_meituan_id = switchMasterHotelInfoDto.getMasterHotelId() + mtHotelDetailDto.getMtHotelId();

                //左移动6位
                double mt_lng = CompareUtil.getDouble(Double.valueOf(mtHotelDetailDto.getMtHotelLongitude()));
                double mt_lat = CompareUtil.getDouble(Double.valueOf(mtHotelDetailDto.getMtHotelLatitude()));

                compareHotel.setMtLat(new BigDecimal(mt_lat).setScale(6, BigDecimal.ROUND_DOWN));
                compareHotel.setMtLng(new BigDecimal(mt_lng).setScale(6, BigDecimal.ROUND_DOWN));


                String mt_hotel_name = mtHotelDetailDto.getMtHotelName();

                compareHotel.setMtHotelId(mtHotelDetailDto.getMtHotelId());
                compareHotel.setMtHotelName(mt_hotel_name);

                //两平台间酒店定位距离，最大可接受差值
                if (algorithm(switch_lat, switch_lng, mt_lat, mt_lng) <= DISTANCE_MAX) {
                    //判断酒店名称
                    if (getStrPre(area_name, switch_hotel_name, mt_hotel_name)) {

                        isCompare = 1;//校验通过
                        //校验状态
                        compareHotel.setIsCompare(isCompare);
                        //如果缓存中不存在之前校验过的数据，则做新增
                        if (!isCompareMap.containsKey(switch_meituan_id)) {
                            compareHotel.setId(StringUtil.getUUID());
                            compareHotel.setRemark(String.valueOf(DISTANCE_MAX));//校验是的多少米范围内
                            compareHotelList.add(compareHotel);

                            switchCompareIdList.add(switchDto.getMasterHotelId());
                            log.info("将美团中校验的数据添加到 switchCompareIdList--->{}", switchCompareIdList.size());

                            mtCompareIdList.add(meituanDto.getId());
                            log.info("将美团中校验的数据添加到mtCompareIdList--->{}", mtCompareIdList.size());

                            //只用到携程母酒店id+美团酒店id，所以做相关新对象初始化
//                            CompareHotel compareHotelNew = new CompareHotel();
//                            compareHotelNew.setSwitchHotelId(compareHotel.getSwitchHotelId());
//                            compareHotelNew.setMtHotelId(compareHotel.getMtHotelId());

                            //添加入map
                            isCompareMap.put(switch_meituan_id, "1");

                        } else {//如果缓存中存在之前校验过的数据，则不做新增
                            return true;
                        }
                    } else {
                        mtNoMatchNameMtIdList.add(meituanDto.getId());
                        log.info("将美团中名称没有校验正确的数据添加至 mtNoMatchNameMtIdList--->mtNoMatchNameMtIdList.size:{}", mtNoMatchNameMtIdList.size());

                        return false;
                    }

                } else {
                    mtNoMatchNameMtIdList.add(meituanDto.getId());
                    log.info("将美团中名称没有校验正确的数据添加至 mtNoMatchNameMtIdList--->mtNoMatchNameMtIdList.size:{}", mtNoMatchNameMtIdList.size());

                    return false;
                }

            } else {
                mtNoMatchNameMtIdList.add(meituanDto.getId());
                log.info("将美团中名称没有校验正确的数据添加至 mtNoMatchNameMtIdList--->mtNoMatchNameMtIdList.size:{}", mtNoMatchNameMtIdList.size());

                return false;
            }

        } else {
            mtNoMatchNameMtIdList.add(meituanDto.getId());
            log.info("将美团中名称没有校验正确的数据添加至 mtNoMatchNameMtIdList--->mtNoMatchNameMtIdList.size:{}", mtNoMatchNameMtIdList.size());

            return false;
        }

        return ret;
    }

    /**
     * 将map 拆分成10等分
     *
     * @param meituanMap
     */

    private Map<String, MtHotelDetailDto> mapThread0 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread1 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread2 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread3 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread4 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread5 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread6 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread7 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread8 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread9 = new HashMap<String, MtHotelDetailDto>();


    private Map<String, MtHotelDetailDto> mapThread10 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread11 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread12 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread13 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread14 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread15 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread16 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread17 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread18 = new HashMap<String, MtHotelDetailDto>();
    private Map<String, MtHotelDetailDto> mapThread19 = new HashMap<String, MtHotelDetailDto>();

    public void hotelMapFetch(Map<String, MtHotelDetailDto> meituanMap) {
        Iterator<Map.Entry<String, MtHotelDetailDto>> iterator = meituanMap.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, MtHotelDetailDto> entry = iterator.next();
            String key = entry.getKey();
            String.valueOf(key);
            int hashCode = Math.abs(String.valueOf(key).hashCode());

            switch (hashCode % THREAD_NUM) {//分割成10份
                case 0:
                    mapThread0.put(key, meituanMap.get(key));
                    break;
                case 1:
                    mapThread1.put(key, meituanMap.get(key));
                    break;
                case 2:
                    mapThread2.put(key, meituanMap.get(key));
                    break;
                case 3:
                    mapThread3.put(key, meituanMap.get(key));
                    break;
                case 4:
                    mapThread4.put(key, meituanMap.get(key));
                    break;
                case 5:
                    mapThread5.put(key, meituanMap.get(key));
                    break;
                case 6:
                    mapThread6.put(key, meituanMap.get(key));
                    break;
                case 7:
                    mapThread7.put(key, meituanMap.get(key));
                    break;
                case 8:
                    mapThread8.put(key, meituanMap.get(key));
                    break;
                case 9:
                    mapThread9.put(key, meituanMap.get(key));
                    break;


                case 10:
                    mapThread10.put(key, meituanMap.get(key));
                    break;
                case 11:
                    mapThread1.put(key, meituanMap.get(key));
                    break;
                case 12:
                    mapThread2.put(key, meituanMap.get(key));
                    break;
                case 13:
                    mapThread13.put(key, meituanMap.get(key));
                    break;
                case 14:
                    mapThread14.put(key, meituanMap.get(key));
                    break;
                case 15:
                    mapThread15.put(key, meituanMap.get(key));
                    break;
                case 16:
                    mapThread16.put(key, meituanMap.get(key));
                    break;
                case 17:
                    mapThread17.put(key, meituanMap.get(key));
                    break;
                case 18:
                    mapThread18.put(key, meituanMap.get(key));
                    break;
                case 19:
                    mapThread19.put(key, meituanMap.get(key));
                    break;

            }
        }

        System.out.println("----程序开始运行----");
        Date date1 = new Date();

        //创建10个线程
        int taskSize = THREAD_NUM;
        // 创建一个线程池
        ExecutorService pool = Executors.newFixedThreadPool(taskSize);
        // 创建多个有返回值的任务
        List<Future> list = new ArrayList<Future>();
        for (int i = 0; i < taskSize; i++) {
            Callable c = new HotelCompareCallable(i + "");
            // 执行任务并获取 Future 对象
            Future f = pool.submit(c);
            // System.out.println(">>>" + f.get().toString());
            list.add(f);
        }
        // 关闭线程池
        pool.shutdown();

        // 获取所有并发任务的运行结果
        for (Future f : list) {
            // 从 Future 对象上获取任务的返回值，并输出到控制台
            try {
                System.out.println(">>>" + f.get().toString());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        Date date2 = new Date();
        System.out.println("----程序结束运行----，程序运行时间【"
                + (date2.getTime() - date1.getTime()) + "毫秒】");
    }


    /**
     * 返回值线程
     */
    class HotelCompareCallable implements Callable<Object> {
        private String taskNum;

        HotelCompareCallable(String taskNum) {
            this.taskNum = taskNum;
        }

        @Override
        public Object call() throws Exception {
            System.out.println(">>>" + taskNum + "任务启动");
            taskNum = taskNum.trim();
            Date dateTmp1 = new Date();
            Thread.sleep(100);
            //根据创建线程调用对应hotelCompareMap 进行校验
            if (Integer.valueOf(taskNum) == 0) {
                compareHotelBySql(mapThread0, taskNum);
            } else if (Integer.valueOf(taskNum) == 1) {
                compareHotelBySql(mapThread1, taskNum);
            } else if (Integer.valueOf(taskNum) == 2) {
                compareHotelBySql(mapThread2, taskNum);
            } else if (Integer.valueOf(taskNum) == 3) {
                compareHotelBySql(mapThread3, taskNum);
            } else if (Integer.valueOf(taskNum) == 4) {
                compareHotelBySql(mapThread4, taskNum);
            } else if (Integer.valueOf(taskNum) == 5) {
                compareHotelBySql(mapThread5, taskNum);
            } else if (Integer.valueOf(taskNum) == 6) {
                compareHotelBySql(mapThread6, taskNum);
            } else if (Integer.valueOf(taskNum) == 7) {
                compareHotelBySql(mapThread7, taskNum);
            } else if (Integer.valueOf(taskNum) == 8) {
                compareHotelBySql(mapThread8, taskNum);
            } else if (Integer.valueOf(taskNum) == 9) {
                compareHotelBySql(mapThread9, taskNum);
            } else if (Integer.valueOf(taskNum) == 10) {
                compareHotelBySql(mapThread10, taskNum);
            } else if (Integer.valueOf(taskNum) == 11) {
                compareHotelBySql(mapThread11, taskNum);
            } else if (Integer.valueOf(taskNum) == 12) {
                compareHotelBySql(mapThread12, taskNum);
            } else if (Integer.valueOf(taskNum) == 13) {
                compareHotelBySql(mapThread13, taskNum);
            } else if (Integer.valueOf(taskNum) == 14) {
                compareHotelBySql(mapThread14, taskNum);
            } else if (Integer.valueOf(taskNum) == 15) {
                compareHotelBySql(mapThread15, taskNum);
            } else if (Integer.valueOf(taskNum) == 16) {
                compareHotelBySql(mapThread16, taskNum);
            } else if (Integer.valueOf(taskNum) == 17) {
                compareHotelBySql(mapThread17, taskNum);
            } else if (Integer.valueOf(taskNum) == 18) {
                compareHotelBySql(mapThread18, taskNum);
            } else if (Integer.valueOf(taskNum) == 19) {
                compareHotelBySql(mapThread19, taskNum);
            }


            Date dateTmp2 = new Date();
            long time = dateTmp2.getTime() - dateTmp1.getTime();
            System.out.println(">>>" + taskNum + "任务终止");
            return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
        }
    }

    /**
     * 获取校验后的酒店信息
     *
     * @return
     */
    @Override
    public List<CompareHotel> getCompareHotel() {
        List<CompareHotel> compareHotelList = new ArrayList<>();

        return compareHotelList;
    }

    /**
     * 根据携程master_hotel_id 获取校验后酒店信息
     *
     * @param masterHotelId
     * @return
     */
    @Override
    public Result getCompareHotelByMasterHotelId(String masterHotelId) {
        Example example = new Example(CompareHotel.class);
        example.createCriteria().andCondition("switch_hotel_id=", masterHotelId)
                .andCondition("is_compare = 1");//校验成功的数据
        List<CompareHotel> list = compareHotelMapper.selectByExample(example);
        return new Result<>(list.size() > 0 ? list.get(0) : null);
    }

    /**
     * 返回一条未创建子酒店的母酒店id
     * 条件 is_create_sub = 0 未创建子酒店
     *
     * @return
     */
    @Override
    public Result<Object> queryOneNotCreateMasterHotelId(Integer index, Integer pageSize) {

        Long masterId = null;

        List<SwitchHotelOnlineSetEntity> all = switchHotelOnlineSetMapper.allSet();
        if(null != all && all.size()>0){
            log.info("queryOneNotCreateMasterHotelId 过滤配置表，只创建配置表指定的酒店 all：{},i={},pageSize={}", JSON.toJSONString(all),index,pageSize);
            //要过滤配置表，只创建配置表指定的酒店
            Map findMap = new HashMap();
            findMap.put("index", index);
            findMap.put("pageSize", pageSize);
            List<SwitchHotelOnlineSetEntity> switchHotelOnlineSetEntityList = switchHotelOnlineSetMapper.queryPageDto(findMap);
            log.info("queryOneNotCreateMasterHotelId 过滤配置表，只创建配置表指定的酒店 switchHotelOnlineSetEntityList：{},i={},pageSize={}", JSON.toJSONString(switchHotelOnlineSetEntityList));
            if (null == switchHotelOnlineSetEntityList || switchHotelOnlineSetEntityList.size() == 0) {
                log.info("/////// queryOneNotCreateMasterHotelId  无下一城市配置");
                return new Result<>(null,"success");//城市设置已无数据 返回data=null
            }
            SwitchHotelOnlineSetEntity switchHotelOnlineSetEntity = switchHotelOnlineSetEntityList.get(0);
            Byte sold = switchHotelOnlineSetEntity.getSold();
            log.info("queryOneNotCreateMasterHotelId 过滤配置表，只创建配置表指定的酒店 sold：{}",sold);
            Map findMasterMap = new HashMap();
            if(sold == 1){
                //指定酒店
                if(!StringUtils.isEmpty(switchHotelOnlineSetEntity.getIds())){
                    String[] idsArray = switchHotelOnlineSetEntity.getIds().split(",");
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i <idsArray.length; i++) {
                        sb.append("'"+idsArray[i]+"'");
                        if(i!=idsArray.length-1){
                            sb.append(",");
                        }
                    }
                    findMasterMap.put("hotelIdsInfo", sb.toString());
                }
            }else{
                findMasterMap.put("provinceId", switchHotelOnlineSetEntity.getProvinceId());
                findMasterMap.put("cityName", switchHotelOnlineSetEntity.getCityName());
                findMasterMap.put("min", switchHotelOnlineSetEntity.getMinStar());
                findMasterMap.put("max", switchHotelOnlineSetEntity.getMaxStar());
            }
            log.info("queryOneNotCreateMasterHotelId 过滤配置表，只创建配置表指定的酒店 findMasterMap：{}", JSON.toJSONString(findMasterMap));
            masterId = compareHotelMapper.findOneNotCreateMasterHotel(findMasterMap);

            log.info("queryOneNotCreateMasterHotelId 过滤配置表，只创建配置表指定的酒店 masterId：{}",masterId);

            Map resultMap = new HashMap();
            resultMap.put("masterId", String.valueOf(masterId));//顺序获取 一个母酒店id
            if (null == masterId) {
                resultMap.put("index", index + 1);//城市基础设置 下一页
            } else {
                resultMap.put("index", index);//城市基础设置 当前页
            }
            log.info("queryOneNotCreateMasterHotelId 过滤配置表 resultMap：{}", JSON.toJSONString(resultMap));
            return new Result<>(resultMap);

        }else{
            //创建不过滤配置表，读compare全表根据一定条件
            log.info("queryOneNotCreateMasterHotelId 创建不过滤配置表，读compare全表根据一定条件");

            masterId = compareHotelMapper.findOneNotCreateMasterHotelNotSet();

            Map resultMap = new HashMap();
            resultMap.put("masterId", String.valueOf(masterId));//顺序获取 一个母酒店id
            if (null == masterId) {
                return new Result<>();
            }
            resultMap.put("type","1");
            log.info("queryOneNotCreateMasterHotelId 创建不过滤配置表 读compare全表根据一定条件 resultMap：{}", JSON.toJSONString(resultMap));
            return new Result<>(resultMap);

        }

    }

    @Override
    public Result<Object> updateCompareMasterIsCreateSub(String masterHotelId, Integer isCreateSub, String isCreateSubReamrk) {
        Map map = new HashMap();
        map.put("masterHotelId", masterHotelId);
        map.put("isCreateSub", isCreateSub);
        map.put("isCreateSubRemark", isCreateSubReamrk);
        map.put("modifyTime", DateUtil.getCurrTime());
        compareHotelMapper.updateCompareMasterIsCreateSub(map);
        try{
            this.saveCreateSubHotelLog(masterHotelId,isCreateSub,isCreateSubReamrk);
        }catch (Exception e){
            log.error("saveCreateSubHotelLog失败："+e.getMessage());
            e.printStackTrace();
        }
        return new Result<>();
    }

    /**
     * 保存创建子酒店日志
     * @param masterHotelId
     * @param isCreateSub
     * @param isCreateSubReamrk
     */
    private void saveCreateSubHotelLog(String masterHotelId, Integer isCreateSub, String isCreateSubReamrk) {
        CompareCreateSubHotelLog compareCreateSubHotelLog = new CompareCreateSubHotelLog();
        compareCreateSubHotelLog.setId(StringUtil.getUUID());
        compareCreateSubHotelLog.setIsCreateSubReamrk(isCreateSubReamrk);
        compareCreateSubHotelLog.setIsCreateSub(isCreateSub);
        compareCreateSubHotelLog.setMasterHotelId(masterHotelId);
        compareCreateSubHotelLog.setCreateTime(new Date());
        compareCreateSubHotelLog.setModifyTime(compareCreateSubHotelLog.getCreateTime());
        compareCreateSubHotelLogMapper.insert(compareCreateSubHotelLog);
    }

    /**
     * 根据携程酒店id获取对应的美团id
     *
     * @param masterHotelId
     * @return
     */
    @Override
    public String getCompareMtHotelId(int masterHotelId) {
        return compareHotelMapper.getCompareMtHotelId(masterHotelId);
    }

    /*************************************根据酒店电话/地址 校验数据**************************************************/

    /**
     * 1:根据酒店电话校验美团-携程酒店是否一致
     * 2:根据酒店地址...
     */

    public int mtCount = 0;
    @Override
    public void compareHotelByPhone() {
        //获取未校验的携程酒店所有信息
//        List<SwitchMasterHotelInfo> switchHotelListCompare = new ArrayList<>();
//        switchHotelListCompare = switchMasterHotelInfoMapper.findSwitchHotelCompare();
//        log.info("{}", switchHotelListCompare.size());

        //直接从数据库 获取所有未校验的美团酒店数据
        List<MtHotelDetail> mtHotelDetailList = new ArrayList<>();
        mtHotelDetailList = mtHotelDetailMapper.findMeituanHotelCompare();
        try {
            String ret = list2Hotel(mtHotelDetailList,1);
            log.info("list2Hotel--ret: {}",ret);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public Result<Object> findNotCreateMtHotelId() {
        Map map = new HashMap();
        map.put("isCompare", 3);
        map.put("isCreateSub", 0);
        List<Long> list = compareHotelMapper.findNotCreateMtHotelId(map);
        return new Result<>(list);
    }

    /**
     * <H1>获取美团ID</H1>
     *
     * @param compareHotelForFpVO    实体对象
     * @return hotel.base.oversea.utils.Result<java.util.List<java.lang.String>>
     * @author HuangT
     * @Date 2020/9/21 20:50
    */
//    @Override
//    public Result<List<CompareRoomForFpVO>> getMtHotelIds(CompareHotelForFpVO compareHotelForFpVO) {
//        //PageHelper.startPage(compareHotelForFpVO.getPageCode(), compareHotelForFpVO.getPageSize());
//        List<CompareRoomForFpVO> mtHotelIdList = compareHotelMapper.getMtHotelIds(compareHotelForFpVO);
//        return new Result<>(mtHotelIdList);
//    }


    public String list2Hotel(List<MtHotelDetail> list, int nThreads)
            throws Exception {
        if (list == null || list.isEmpty()) {
            return null;
        }
        StringBuffer ret = new StringBuffer();

        long start = System.currentTimeMillis();
        int size = list.size();
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
        List<Future<String>> futures = new ArrayList<Future<String>>(nThreads);
        for (int i = 0; i < nThreads; i++) {
            final List<MtHotelDetail> subList = list.subList(size / nThreads * i, size/ nThreads * (i + 1));
            log.info("subList.size --> {}",subList.size());
            int finalI = i;
            Callable<String> task = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    List<CompareHotel> retCompareList = new ArrayList<CompareHotel>();
//                    retCompareList = compareMapVoid(subList, finalI);//字段全匹配
                    retCompareList = compareMapPhoneOtherVoid(subList,finalI);//美团酒店带 / 进行拆分，模糊匹配
                    return String.valueOf(retCompareList.size());
                }
            };
            futures.add(executorService.submit(task));
            Thread.sleep(10);
        }

//        for (Future<String> future : futures) {
//            log.info("进入 for (Future<String> future : futures) {} -->");
////            log.info("subList.size --> {}",future.isDone());
//            ret.append(future.get());
//        }
        executorService.shutdown();

        log.info("进入 executorService.shutdown() -->");
        while (true) {
            if (executorService.isTerminated()) {
                log.info("进入 executorService.isTerminated() -->");
                if (!compareHotelList.isEmpty()) {
                    log.info("进入 !compareHotelList.isEmpty() -->");
                    for(int i=0;i<compareHotelList.size();i++){
                        String idTemp = compareHotelList.get(i).getId();
                        for(int j=0;j<compareHotelList.size();j++){
                            if(j != i){
                                CompareHotel compareHotel = new CompareHotel();
                                compareHotel = compareHotelList.get(j);
                                String idTempJ = compareHotel.getId();
                                if(idTemp == idTempJ){
                                    log.info("compareHotel 数据重复 ---> {}  --- {}",JacksonUtil.objectToJson(compareHotelList.get(i)),JacksonUtil.objectToJson(compareHotel));
                                    CompareHotel compareHotelNew = new CompareHotel();
                                    compareHotelNew = compareHotel;
                                    compareHotelList.remove(j);
                                    compareHotelNew.setId(StringUtil.getUUID());
                                    compareHotelList.add(compareHotelNew);
                                }
                            }
                        }
                    }

                    countTotal = compareHotelList.size();
                    int insInt = 0;
                    if (countTotal > 1000) {
                        int num  = 5;
                        for (int i = 0; i < num; i++) {
                            final List<CompareHotel> addList = compareHotelList.subList(countTotal / num * i, countTotal/ num * (i + 1));
                            log.info("addList.size --> {}",addList.size());

                            insInt = compareHotelMapper.insertList(addList);

                            if(insInt != -1){
                                log.info("num={} ;酒店校验成功总数 并 新增成功： {} 条！",num,insInt);
                            }
                        }
                    }else{
                        insInt = compareHotelMapper.insertList(compareHotelList);

                        if(insInt != -1){
                            log.info("酒店校验成功总数 并 新增成功： {} 条！",insInt);
                        }
                    }
                }
                break;
            }
        }
        log.info("ret --> {}",ret.toString());
        return ret.toString();
    }


    /**
     * 通过手机号全匹配校验
     * @param mtHotelDetailList
     * @param nThreads
     * 2020-08-01
     * @return
     */
    public List<CompareHotel> compareMapVoid(List<MtHotelDetail> mtHotelDetailList,int nThreads){
        List<CompareHotel> retCompareHotelList = new ArrayList<CompareHotel>();
        boolean ret = false;
        if (!mtHotelDetailList.isEmpty() && mtHotelDetailList.size() > 0) {
            mtCount = mtHotelDetailList.size();
            mtHotelFor:mtHotelDetailList.forEach(mtHotelDetail -> {
                mtCount--;
                String mtPhone = mtHotelDetail.getMtPhone();
                if(mtCount <= 0){
                    log.info("----> 线程：{} ；当前已校验待新增数据有: {} ; 美团酒店电话： {} ; ",nThreads,compareHotelList.size(),mtPhone );
                    if (!compareHotelList.isEmpty() ) {
                        int insInt = compareHotelMapper.insertList(compareHotelList);
                        if (insInt > 0) {
                            countTotal += insInt;
                            log.info("酒店校验成功新增 {} 条！",compareHotelList.size());
                            compareHotelList = new ArrayList<CompareHotel>();
                        }

                    }

                    compareHotelList.addAll(retCompareHotelList);
                    log.info("----> 当前美团酒店遍历完成！");
                    throw new RuntimeException();
                }

//                log.info("线程：{}  美团酒店还剩 {} 条，未执行！",nThreads, mtCount);
                if (!ObjectUtils.isEmpty(mtHotelDetail) && !ObjectUtils.isEmpty(mtHotelDetail.getMtPhone())) {


                    //左移动6位
                    double mt_lng = CompareUtil.getDouble(Double.valueOf(mtHotelDetail.getMtHotelLongitude()));
                    double mt_lat = CompareUtil.getDouble(Double.valueOf(mtHotelDetail.getMtHotelLatitude()));


//                    log.info("美团酒店电话： {}", mtPhone);
                    //直接通过酒店电话判断
                    List<SwitchMasterHotelInfo> switchMasterHotelInfoList = new ArrayList<>();
                    SwitchMasterHotelInfo switchMasterHotelInfo = new SwitchMasterHotelInfo();
                    Example example = new Example(SwitchMasterHotelInfo.class);
                    Example.Criteria criteria = example.createCriteria();
                    //全量相等
                    criteria.andEqualTo("hotelPhone", mtHotelDetail.getMtPhone());
                    switchMasterHotelInfoList = switchMasterHotelInfoMapper.selectByExample(example);


//                    log.info("switchMasterHotelInfoList : {}", switchMasterHotelInfoList);
                    int smhilSize = switchMasterHotelInfoList.size();
                    lastMtSw = 0.0;//重新初始化
                    doubleSwtichMap = new HashMap<>();//重新初始化
                    switchMasterHotelInfoList.forEach(switchMasterHotelInfoNew ->{
                        //存在则修改
                        if (!ObjectUtils.isEmpty(switchMasterHotelInfoNew)) {

                            double switch_lng = 0.000000;
                            double switch_lat = 0.000000;

                            //优先判断google,高德坐标，百度
                            if (!ObjectUtils.isEmpty(switchMasterHotelInfoNew.getGgLat()) && !ObjectUtils.isEmpty(switchMasterHotelInfoNew.getGgLng())) {
                                switch_lng = switchMasterHotelInfoNew.getGgLng().doubleValue();
                                switch_lat = switchMasterHotelInfoNew.getGgLat().doubleValue();
                            }

                            double lenMtSw = algorithm(switch_lat, switch_lng, mt_lat, mt_lng);
                            if(BigDecimal.valueOf(lastMtSw).compareTo(BigDecimal.ZERO) == 0){
                                lastMtSw = lenMtSw;
                            }

                            //酒店名称
                            String switch_hotel_name = switchMasterHotelInfoNew.getHotelName();
                            //地区城市名称
                            String area_name = switchMasterHotelInfoNew.getCityName();

                            String mt_hotel_name = mtHotelDetail.getMtHotelName();
                            //两平台间酒店定位距离，最大可接受差值
                            if (smhilSize == 1 ||  (smhilSize > 1 && lenMtSw <= 100 && getStrPre(area_name, switch_hotel_name, mt_hotel_name) && lenMtSw <= lastMtSw) ) {

//                                log.info("携程酒店电话 - 美团酒店电话： {} - {} ", switchMasterHotelInfoNew.getHotelPhone(), mtPhone);
                                CompareHotel compareHotel = new CompareHotel();

                                String uuid = StringUtil.getUUID();

                                if(ObjectUtils.isEmpty(uuid)){
                                    log.warn("--->  uuid is null; ");
                                }

                                compareHotel.setId(uuid);
                                compareHotel.setIsCreateSub(0);
                                compareHotel.setIsType(2);//电话
                                compareHotel.setMtHotelId(mtHotelDetail.getMtHotelId());
                                compareHotel.setMtHotelName(mtHotelDetail.getMtHotelName());
                                compareHotel.setSwitchHotelId(switchMasterHotelInfoNew.getMasterHotelId());
                                compareHotel.setSwitchHotelName(switchMasterHotelInfoNew.getHotelName());
                                compareHotel.setState(0);
                                compareHotel.setIsCompare(1);
                                compareHotel.setRemark("通过手机号全匹配校验，并且坐标相距("+lenMtSw+"米内)");
                                compareHotel.setCreateTime(new Date());
                                compareHotel.setModifyTime(new Date());

                                compareHotel.setMtLat(new BigDecimal(mt_lat).setScale(6, BigDecimal.ROUND_DOWN));
                                compareHotel.setMtLng(new BigDecimal(mt_lng).setScale(6, BigDecimal.ROUND_DOWN));


                                compareHotel.setSwitchLat(new BigDecimal(switch_lat).setScale(6, BigDecimal.ROUND_DOWN));
                                compareHotel.setSwitchLng(new BigDecimal(switch_lng).setScale(6, BigDecimal.ROUND_DOWN));

                                doubleSwtichMap.put(mtHotelDetail.getMtHotelId(),compareHotel);
                            }

                        }
                    });

                    if(doubleSwtichMap.containsKey(mtHotelDetail.getMtHotelId())){
                        compareHotelList.add(doubleSwtichMap.get(mtHotelDetail.getMtHotelId()));
                    }

                    log.info("----> 线程：{} ；当前已校验待新增数据有: {} ; 美团酒店电话： {} ; ",nThreads,compareHotelList.size(),mtPhone );
                    if (!compareHotelList.isEmpty() && compareHotelList.size() >= 500) {
                        int insInt = compareHotelMapper.insertList(compareHotelList);
                        if (insInt > 0) {
                            countTotal += insInt;
                            log.info("酒店校验成功新增 {} 条！",compareHotelList.size());
                            compareHotelList = new ArrayList<CompareHotel>();
                        }

                    }

                } else {
                    log.info("美团酒店电话为空！ {}",mtHotelDetail);
                }

            });


        }

        return retCompareHotelList;
    }

    /**
     * 通过手机号互相包含匹配校验
     * @param mtHotelDetailList
     * @param nThreads
     * 2020-09-09
     * @return
     */
    public synchronized List<CompareHotel> compareMapPhoneOtherVoid(List<MtHotelDetail> mtHotelDetailList,int nThreads){
        List<CompareHotel> retCompareHotelList = new ArrayList<CompareHotel>();
        boolean ret = false;
        if (!mtHotelDetailList.isEmpty() && mtHotelDetailList.size() > 0) {
            mtCount = mtHotelDetailList.size();
            mtHotelFor:mtHotelDetailList.forEach(mtHotelDetail -> {
                mtCount--;
                String mtPhone = mtHotelDetail.getMtPhone();
                if(mtCount <= 0){
                    log.info("----> 线程：{} ；当前已校验待新增数据有: {} ; 美团酒店电话： {} ; ",nThreads,compareHotelList.size(),mtPhone );
                    if (!compareHotelList.isEmpty() ) {
                        int insInt = compareHotelMapper.insertList(compareHotelList);
                        if (insInt > 0) {
                            countTotal += insInt;
                            log.info("酒店校验成功新增 {} 条！",compareHotelList.size());
                            compareHotelList = new ArrayList<CompareHotel>();
                        }

                    }

                    compareHotelList.addAll(retCompareHotelList);
                    log.info("----> 当前美团酒店遍历完成！");
                    throw new RuntimeException();
                }

//                log.info("线程：{}  美团酒店还剩 {} 条，未执行！",nThreads, mtCount);
                if (!ObjectUtils.isEmpty(mtHotelDetail) && !ObjectUtils.isEmpty(mtHotelDetail.getMtPhone())) {

                    //左移动6位
                    double mt_lng = CompareUtil.getDouble(Double.valueOf(mtHotelDetail.getMtHotelLongitude()));
                    double mt_lat = CompareUtil.getDouble(Double.valueOf(mtHotelDetail.getMtHotelLatitude()));


//                    log.info("美团酒店电话： {}", mtPhone);
                    //直接通过酒店电话判断
                    List<SwitchMasterHotelInfo> switchMasterHotelInfoList = new ArrayList<>();
                    SwitchMasterHotelInfo switchMasterHotelInfo = new SwitchMasterHotelInfo();
                    Example example = new Example(SwitchMasterHotelInfo.class);
                    Example.Criteria criteria = example.createCriteria();
                    //判断是否存在多个电话号码
                    mtPhone = mtHotelDetail.getMtPhone();
                    String[] arrMtPhone = null;
                    if(mtPhone.indexOf("/") != -1){
                        arrMtPhone = mtPhone.split("/");
                        if(arrMtPhone.length>0){
                            for(int i=0;i<arrMtPhone.length;i++){
                                String tempPhone = arrMtPhone[i];
                                criteria.orLike("hotelPhone", tempPhone);
                            }
                        }

                    }else{
                        criteria.orLike("hotelPhone", mtPhone);
                    }
                    switchMasterHotelInfoList = switchMasterHotelInfoMapper.selectByExample(example);


//                    log.info("switchMasterHotelInfoList : {}", switchMasterHotelInfoList);
                    int smhilSize = switchMasterHotelInfoList.size();
                    lastMtSw = 0.0;//重新初始化
                    doubleSwtichMap = new HashMap<>();//重新初始化
                    switchMasterHotelInfoList.forEach(switchMasterHotelInfoNew ->{
                        //存在则修改
                        if (!ObjectUtils.isEmpty(switchMasterHotelInfoNew)) {

                            double switch_lng = 0.000000;
                            double switch_lat = 0.000000;

                            //优先判断google,高德坐标，百度
                            if (!ObjectUtils.isEmpty(switchMasterHotelInfoNew.getGgLat()) && !ObjectUtils.isEmpty(switchMasterHotelInfoNew.getGgLng())) {
                                switch_lng = switchMasterHotelInfoNew.getGgLng().doubleValue();
                                switch_lat = switchMasterHotelInfoNew.getGgLat().doubleValue();
                            }

                            double lenMtSw = algorithm(switch_lat, switch_lng, mt_lat, mt_lng);
                            if(BigDecimal.valueOf(lastMtSw).compareTo(BigDecimal.ZERO) == 0){
                                lastMtSw = lenMtSw;
                            }

                            //酒店名称
                            String switch_hotel_name = switchMasterHotelInfoNew.getHotelName();
                            //地区城市名称
                            String area_name = switchMasterHotelInfoNew.getCityName();

                            String mt_hotel_name = mtHotelDetail.getMtHotelName();
                            //两平台间酒店定位距离，最大可接受差值
                            if (smhilSize == 1 ||  (smhilSize > 1 && lenMtSw <= 100 && getStrPre(area_name, switch_hotel_name, mt_hotel_name) && lenMtSw <= lastMtSw) ) {

//                                log.info("携程酒店电话 - 美团酒店电话： {} - {} ", switchMasterHotelInfoNew.getHotelPhone(), mtPhone);
                                CompareHotel compareHotel = new CompareHotel();

                                String uuid = StringUtil.getUUID();

                                if(ObjectUtils.isEmpty(uuid)){
                                    log.warn("--->  uuid is null; ");
                                }

                                compareHotel.setId(uuid);
                                compareHotel.setIsCreateSub(0);
                                compareHotel.setIsType(2);//电话
                                compareHotel.setMtHotelId(mtHotelDetail.getMtHotelId());
                                compareHotel.setMtHotelName(mtHotelDetail.getMtHotelName());
                                compareHotel.setSwitchHotelId(switchMasterHotelInfoNew.getMasterHotelId());
                                compareHotel.setSwitchHotelName(switchMasterHotelInfoNew.getHotelName());
                                compareHotel.setState(0);
                                compareHotel.setIsCompare(1);
                                compareHotel.setRemark("通过手机号互相包含匹配校验，并且坐标相距("+lenMtSw+"米内)");
                                compareHotel.setCreateTime(new Date());
                                compareHotel.setModifyTime(new Date());

                                compareHotel.setMtLat(new BigDecimal(mt_lat).setScale(6, BigDecimal.ROUND_DOWN));
                                compareHotel.setMtLng(new BigDecimal(mt_lng).setScale(6, BigDecimal.ROUND_DOWN));


                                compareHotel.setSwitchLat(new BigDecimal(switch_lat).setScale(6, BigDecimal.ROUND_DOWN));
                                compareHotel.setSwitchLng(new BigDecimal(switch_lng).setScale(6, BigDecimal.ROUND_DOWN));

                                doubleSwtichMap.put(mtHotelDetail.getMtHotelId(),compareHotel);
                            }

                        }
                    });


                    log.info("----> 线程：{} ；当前已校验待新增数据有: {} ; 美团酒店电话： {} ; ",nThreads,compareHotelList.size(),mtPhone );
//                    synchronized(this){
                        if (!compareHotelList.isEmpty() && compareHotelList.size() >= 500) {
                            int insInt = compareHotelMapper.insertList(compareHotelList);
                            if (insInt > 0) {
                                countTotal += insInt;
                                log.info("酒店校验成功新增 {} 条！",compareHotelList.size());
                                compareHotelList = new ArrayList<CompareHotel>();
                            }

                        }
//                    }


                    if(doubleSwtichMap.containsKey(mtHotelDetail.getMtHotelId())){
                        compareHotelList.add(doubleSwtichMap.get(mtHotelDetail.getMtHotelId()));
                    }
                } else {
                    log.info("美团酒店电话为空！ {}",mtHotelDetail);
                }

            });


        }

        return retCompareHotelList;
    }

    /**
     * 判断电话号码，规则
     *
     * @param phone
     * @return
     */
    public String[] getPhone(String phone) {
        String[] retPhone = {};

        String[] phoneStrs = {};

        String tempCode = "";//电话区号
        phone = phone.replaceAll("/+86-", "").replaceAll("/+886-", "").replaceAll("、", "-").replaceAll("#", "")
                .replaceAll("00886-", "").replaceAll("0086", "");//去掉+86,+886,00886-
        //存在斜杆 拆分  美团
        if (phone.indexOf("/") != -1) {
            phoneStrs = phone.split("/");
            if (phoneStrs.length > 0) {
                for (int i = 0; i < phoneStrs.length; i++) {
                    //String phones : phoneStrs
                    String phones = phoneStrs[i];
                    //存在- 拆分出区号，只为取出 区号
                    if (i == 0) {
                        if (phones.indexOf("-") != -1) {
                            String[] phoneTemps = phones.split("-");
                            tempCode = phoneTemps[0];//区号
                        }
                        //去掉-
                        retPhone[i] = phones.replace("-", "");
                    } else {
                        if (phones.indexOf("-") != -1) {
                            retPhone[i] = phones.replace("-", "");
                        } else {
                            //说明不是手机号
                            if (phones.length() != 11) {
                                retPhone[i] = tempCode + phones;
                            } else {
                                retPhone[i] = phones;
                            }
                        }
                    }

                }

            }
        } else if (phone.indexOf("-") != -1) {
            phoneStrs = phone.split("-");
            if (phoneStrs.length > 0) {
                for (int i = 0; i < phoneStrs.length; i++) {
                    String phones = phoneStrs[i];
                    //存在- 拆分出区号，只为取出 区号
                    if (i == 0) {
                        if (phones.indexOf("-") != -1) {
                            String[] phoneTemps = phones.split("-");
                            tempCode = phoneTemps[0];//区号
                        }
                        //去掉-
                        retPhone[i] = phones.replace("-", "");
                    } else {
                        if (phones.indexOf("-") != -1) {
                            retPhone[i] = phones.replace("-", "");
                        } else {
                            //说明不是手机号
                            if (phones.length() != 11) {
                                retPhone[i] = tempCode + phones;
                            } else {
                                retPhone[i] = phones;
                            }
                        }
                    }

                }
            }
        } else {
            phoneStrs[0] = phone;
        }


        return retPhone;
    }


    /**
     * <H1>获取核验后酒店信息列表</H1>
     *
     * @param compareHotelVO
     * @return hotel.base.oversea.utils.Result
     * @author HuangT
     * @date 2020/7/24 16:39
     */
    @Override
    public Result getCompareHotelList(CompareHotelVO compareHotelVO) {
        PageHelper.startPage(compareHotelVO.getPageNumber(), compareHotelVO.getPageSize());
        List<CompareHotelListVO> compareHotelListList = compareHotelMapper.getCompareHotelList(compareHotelVO);
        for(CompareHotelListVO compareHotelListVO:compareHotelListList){
            String mtHotelId = compareHotelListVO.getMtHotelId();
            MtHotelDetail mtHotelDetail = mtHotelDetailMapper.getHotelInfoByMtHotelId(mtHotelId);
            compareHotelListVO.setMtHotelPhone(mtHotelDetail.getMtPhone());
            //携程酒店ID
            Integer switchHotelId = compareHotelListVO.getSwitchHotelId();
            SwitchMasterHotelInfoDto switchMasterHotelInfoDto = switchMasterHotelInfoMapper.getHotelInfoBySwitchHotelId(switchHotelId);
            compareHotelListVO.setSwHotelPhone(switchMasterHotelInfoDto.getHotelPhone());
            Integer hotelInfo=switchHotelUpMapper.selectByMasterHotelId(compareHotelListVO.getSwitchHotelId());
            //0 待创建  1 正在售卖 2 已创建 3 黑名单
            if(ObjectUtils.isEmpty(hotelInfo)){
                compareHotelListVO.setStatus(0);
            }else{
                if(hotelInfo==3){
                    compareHotelListVO.setStatus(1);
                }else if(hotelInfo==2){
                    compareHotelListVO.setStatus(3);
                }else{
                    compareHotelListVO.setStatus(2);
                }
            }
        }
        PageInfo<CompareHotelListVO> pageInfo = new PageInfo<>(compareHotelListList);
        return new Result<>(pageInfo);
    }

    /**
     * <H1>批量校验通过或不通过</H1>
     *
     * @param compareHotel
     * @return hotel.base.oversea.utils.Result
     * @author HuangT
     * @date 2020/7/30 17:04
    */
    @Override
    public Result changeIsCompare(CompareHotelVO compareHotel) {
        List<String> idList = new ArrayList<>();
        if(null != compareHotel.getId()) {
            idList.add(compareHotel.getId());
        } else {
            String[] ids = compareHotel.getIds();
            idList = Arrays.asList(ids);
        }
        Integer num = compareHotelMapper.changeIsCompare(compareHotel, idList);
        return new Result<>(num);
    }

    @Override
    public Result getHotelInfoById(String id) {
        CompareHotelListVO compareHotel = compareHotelMapper.getHotelInfoById(id);
        //美团酒店ID
        String mtHotelId = compareHotel.getMtHotelId();
        MtHotelDetail mtHotelDetail = mtHotelDetailMapper.getHotelInfoByMtHotelId(mtHotelId);
        compareHotel.setMtHotelCityName(mtHotelDetail.getMtHotelCityName() + "/" + mtHotelDetail.getMtLocationName());
        compareHotel.setMtHotelAddress(mtHotelDetail.getMtHotelAddress());
        compareHotel.setMtHotelPhone(mtHotelDetail.getMtPhone());
        //携程酒店ID
        Integer switchHotelId = compareHotel.getSwitchHotelId();
        SwitchMasterHotelInfoDto switchMasterHotelInfoDto = switchMasterHotelInfoMapper.getHotelInfoBySwitchHotelId(switchHotelId);
        compareHotel.setHotelAddress(switchMasterHotelInfoDto.getHotelAddress());
        compareHotel.setCityName(switchMasterHotelInfoDto.getCityName());
        compareHotel.setSwHotelPhone(switchMasterHotelInfoDto.getHotelPhone());
        return new Result<>(compareHotel);
    }

    /**
     * <H1>新增对比酒店</H1>
     *
     * @param compareHotelVO
     * @return hotel.base.oversea.utils.Result
     * @author HuangT
     * @date 2020/8/10 15:57
    */
    @Override
    public Result addCompare(CompareHotelVO compareHotelVO) {
        CompareHotel compareHotel = new CompareHotel();
        BeanCopier beanCopier = BeanCopier.create(CompareHotelVO.class, CompareHotel.class, false);
        beanCopier.copy(compareHotelVO,compareHotel,null);
        //生成ID
        String id = UUID.randomUUID().toString();
        compareHotel.setId(id);
        //手动增加
        compareHotel.setIsType(1);
        //通过
        compareHotel.setIsCompare(1);
        //设置成0米
        compareHotel.setRemark("0");
        //系统状态
        compareHotel.setState(0);
        //创建子酒店状态
        compareHotel.setIsCreateSub(0);
        compareHotel.setCreateTime(new DateTime());
        compareHotel.setModifyTime(new DateTime());

        int insert = 0;
        try {
            insert = compareHotelMapper.insert(compareHotel);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("手动新增对比酒店失败: {}", e.getMessage());
        }
        if(insert >= 1) {
            return new Result<>(insert,"新增成功");
        } else {
            return new Result<>(insert,"新增失败");
        }

    }

    /**
     * <H1>新增前验证是否存在已验证通过的酒店</H1>
     *
     * @param compareHotel
     * @return hotel.base.oversea.utils.Result
     * @author HuangT
     * @date 2020/8/10 18:32
    */
    @Override
    public Result checkExist(CompareHotelVO compareHotel) {
        List<CompareHotelListVO> compareHotelList = compareHotelMapper.checkExist(compareHotel);
        String msg;
        if(CollectionUtil.isNotEmpty(compareHotelList)) {
            msg = "所输入的id已存在校验过的相应酒店,请校验!";
            return new Result<>(msg, CommonConstants.SUCCESS);
        } else {
            return new Result<>(null, CommonConstants.SUCCESS);
        }

    }

    /**
     * 导入待创建酒店数据
     * @param excelFile
     * @return
     */
    @Override
    @Transactional
    public Result<Object> submitUploadUp(MultipartFile excelFile) {
        List<CompareHotelUp> compareHotelUps = new ArrayList<>();
        List<Integer> mtHotelId=new ArrayList<>();
        try {
            Workbook workbook = WorkbookFactory.create(excelFile.getInputStream());
            excelFile.getInputStream().close();
            //工作表对象
            Sheet sheet = workbook.getSheetAt(0);
            tab:
            for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
                Row sheetRow = sheet.getRow(i);
                Cell cell = sheetRow.getCell(0);
                cell.setCellType(CellType.NUMERIC);
                Double hotelId = cell.getNumericCellValue();
                /*cell = sheetRow.getCell(1);
                cell.setCellType(CellType.STRING);
                String hotelName = cell.getStringCellValue();*/
                CompareHotelUp compareHotelUp = compareHotelUpMapper.selectByMtHotelId(hotelId.intValue());
                if (!ObjectUtil.isEmpty(compareHotelUp)) {
                    continue tab;
                }
                compareHotelUp=new CompareHotelUp();
                compareHotelUp.setMtHotelId(hotelId.intValue());
                compareHotelUp.setMtHotelName("新酒店");
                compareHotelUp.setUp(0);
                compareHotelUps.add(compareHotelUp);
                mtHotelId.add(hotelId.intValue());
            }
        } catch (InvalidFormatException | IOException e) {
            e.printStackTrace();
        }
        if(compareHotelUps.size()>0){
            compareHotelUpMapper.insertList(compareHotelUps);
        }
        if(mtHotelId.size()>0){
            int t=compareHotelMapper.updateIsCreateStatusByMtHotelId(mtHotelId);
            if(t>0){
                compareHotelUpMapper.updateMtHotelId(mtHotelId);
            }
        }
        return new Result<>();

    }
    /***
    * @Author: lmf
    * @Date: 2020/12/11
     * 根据美团的酒店下线记录操作信息
    */
    @Override
    public Integer getCompareHotelId(int mtHotelId) {
        Integer masterHotelId =compareHotelMapper.getCompareHotelId(mtHotelId);
        if(ObjectUtils.isEmpty(masterHotelId)){
            return 0;
        }else{
            Integer hotelId=switchCreateSubHotelMapper.selectHotelIdByMasterHotelId(masterHotelId);
            return hotelId;
        }
    }


}
